package com.mc.fastkit.utils

import android.os.Handler
import android.os.Looper
import android.view.LayoutInflater
import android.widget.TextView
import android.widget.Toast
import com.mc.fastkit.R
import com.mc.fastkit.ext.app
import com.mc.fastkit.ext.isMainThread
import com.mc.fastkit.log.LogUtils
import com.mc.fastkit.log.Priority
import com.mc.fastkit.widget.ActivityStack
import java.lang.ref.WeakReference

/**
 * 旨在解决线程Toast、重复Toast问题
 * @author: MasterChan
 * @date: 2022-06-08 21:20
 */
object ToastUtils {

    private var toast: WeakReference<Toast>? = null
    private var mainHandler: WeakReference<Handler>? = null
    private var lastMills = 0L
    private var lastText: CharSequence = ""
    private var config: Config? = null

    /**
     * 自定义View中，必须包含[R.id.tv_toast_message]的TextView
     */
    var customViewRes = 0

    fun setConfig(config: Config?) {
        this.config = config
    }

    @JvmStatic
    fun show(text: CharSequence, newConfig: Config? = null) {
        show(text, Toast.LENGTH_SHORT, newConfig)
    }

    @JvmStatic
    fun showLong(text: CharSequence, newConfig: Config? = null) {
        show(text, Toast.LENGTH_LONG, newConfig)
    }

    @JvmStatic
    fun show(
        text: CharSequence,
        duration: Int,
        newConfig: Config? = null,
        stackTraceElement: StackTraceElement? = null
    ) {
        if (text == lastText) {
            if (System.currentTimeMillis() - lastMills > 2000) {
                safeShow(text, duration, newConfig, stackTraceElement)
            }
        } else {
            safeShow(text, duration, newConfig, stackTraceElement)
        }
    }

    fun cancel() {
        toast?.get()?.cancel()
    }

    private fun safeShow(
        text: CharSequence,
        duration: Int,
        config: Config?,
        stackTraceElement: StackTraceElement?
    ) {
        val newConfig = config ?: this.config
        if (isMainThread) {
            doShow(text, duration, newConfig, stackTraceElement)
        } else {
            if (mainHandler == null || mainHandler!!.get() == null) {
                mainHandler = WeakReference(Handler(Looper.getMainLooper()))
            }
            mainHandler!!.get()!!.post { doShow(text, duration, newConfig, stackTraceElement) }
        }
    }

    private fun doShow(
        text: CharSequence,
        duration: Int,
        config: Config?,
        stackTraceElement: StackTraceElement?
    ) {
        toast?.get()?.cancel()
        toast = WeakReference(Toast.makeText(app, "", duration))
        toast!!.get()!!.apply {
            setGravity(
                config?.gravity ?: gravity, config?.xOffset ?: xOffset, config?.yOffset ?: yOffset
            )
            if (customViewRes != 0 && ActivityStack.instance.isAppForeground) {
                view = LayoutInflater.from(ActivityStack.instance.top)
                    .inflate(customViewRes, null)
                    .apply { findViewById<TextView>(R.id.tv_toast_message).text = text }
            } else {
                setText(text)
            }
        }.show()
        lastText = text
        lastMills = System.currentTimeMillis()
        LogUtils.print(
            Priority.DEBUG, LogUtils.tag,
            stackTraceElement ?: StackTraceUtils.getTargetStackTraceElement(javaClass.name), text
        )
    }

    data class Config(val gravity: Int, val xOffset: Int = 0, val yOffset: Int = 0)
}